import { type IRendererOptions, type IBaseData } from '../types'

export interface WorkerState {
  bufferCtx: OffscreenCanvasRenderingContext2D
  options: IRendererOptions
  scrollTop: number
  scrollLeft: number
  totalColumnWidth: number
  selectedRowIndices: any[]
  hoverRow: number
  width: number
  height: null
}

export interface IWorderMessageData {
  type: 'init' | 'render'
  bufferCanvas?: OffscreenCanvas
  options?: IRendererOptions
  workerState: Omit<WorkerState, 'bufferCtx'>
  data?: IBaseData[]
}

interface IWorkerMessageEvent extends MessageEvent {
  data: IWorderMessageData
}

let state: WorkerState
let rowDataMap: Record<number, any> = {}

self.onmessage = (e: IWorkerMessageEvent) => {
  const { type } = e.data

  switch (type) {
    case 'init':
      init(e.data)
      break
    case 'render':
      setState(e.data)
      render()
      break
  }
}

function setState (workerState: IWorderMessageData) {
  state = {
    ...(state ?? {}),
    ...workerState.workerState,
  }

  handleUpdateData(state.options.dataSource ?? [])
}

function init (data: IWorderMessageData) {
  state = {
    bufferCtx: data.bufferCanvas.getContext('2d'),
    options: data.options
  };

  // 设置缩放和默认样式
  [state.bufferCtx].forEach(ctx => {
    ctx.scale(state.options.dpr, state.options.dpr)
    ctx.textBaseline = 'middle'
  })
}

function handleUpdateData (data: IBaseData[]): void {
  rowDataMap = {}
  data.forEach((row, index) => {
    rowDataMap[index] = row
  })
  render()
}

function render () {
  const { bufferCtx, options, scrollTop, scrollLeft } = state
  const { width, height, rowHeight } = options
  const totalRows = Object.keys(rowDataMap).length

  // 计算可见区域
  const visibleRowCount = Math.floor(height / rowHeight) + 2 // 增加 2 行缓冲区
  const startRow = Math.floor((scrollTop ?? 0) / rowHeight)
  const endRow = Math.min(startRow + visibleRowCount, totalRows)

  // 总列宽（支持动态列宽，包含勾选列）
  let totalColumnWidth = options.columns.reduce((total, col) => total + (col.width || 120), 0)
  if (options.selectionMode) {
    totalColumnWidth += 40 // 添加勾选列宽度
  }

  const maxScrollLeft = Math.max(0, totalColumnWidth - width)
  const clampedScrollLeft = Math.max(0, Math.min(scrollLeft || 0, maxScrollLeft))

  // 清除画布
  bufferCtx.fillStyle = '#fff'
  bufferCtx.fillRect(0, 0, bufferCtx.canvas.width, bufferCtx.canvas.height)

  // 渲染所有行
  for (let i = startRow; i < endRow; i++) {
    const rowData = rowDataMap[i]
    if (!rowData) continue

    const yPos = (i - startRow) * rowHeight
    // 新增：检查当前行是否是悬停行或选中行
    const isHovered = state.hoverRow === i

    renderRow(i, rowData, yPos, clampedScrollLeft, isHovered)
  }

  // 渲染表头（也应用水平偏移）
  renderHeader(clampedScrollLeft)

  // 交换缓冲
  swapBuffers()
}

function renderHeader (scrollLeft: number) {
  const { bufferCtx, options } = state
  const { rowHeight } = options
  let xPos = -scrollLeft // 使用负值实现表头像素级滚动

  // 表头背景
  bufferCtx.fillStyle = '#f5f5f5'
  bufferCtx.fillRect(0, 0, options.width, rowHeight)

  // 插入左侧勾选框（仅当 selectionMode 存在时）
  if (options.selectionMode) {
    // 勾选框背景
    bufferCtx.fillStyle = '#f5f5f5'
    bufferCtx.fillRect(xPos, 0, 40, rowHeight)

    // 勾选框边框
    bufferCtx.strokeStyle = '#b1b1b1'
    bufferCtx.lineWidth = 1
    bufferCtx.beginPath()
    bufferCtx.rect(xPos + 6, 10, 14, 14)
    bufferCtx.stroke()

    // 底部边框（与其他列保持一致）
    bufferCtx.strokeStyle = '#e0e0e0'
    bufferCtx.beginPath()
    bufferCtx.moveTo(xPos, rowHeight - 0.5)
    bufferCtx.lineTo(xPos + 40, rowHeight - 0.5)
    bufferCtx.stroke()

    xPos += 40
  }

  // 绘制列
  options.columns.forEach((col, colIndex) => {
    const colWidth = col.width || 120

    // 列边框
    bufferCtx.strokeStyle = '#e0e0e0'
    bufferCtx.lineWidth = 1
    bufferCtx.beginPath()

    // 左侧边框（仅第一列）
    if (colIndex === 0 && !options.selectionMode) {
      bufferCtx.moveTo(xPos + 0.5, 0)
      bufferCtx.lineTo(xPos + 0.5, rowHeight)
    }

    bufferCtx.moveTo(xPos + colWidth - 0.5, 0)
    bufferCtx.lineTo(xPos + colWidth - 0.5, rowHeight)

    // 底部边框（所有列统一绘制）
    bufferCtx.moveTo(xPos, rowHeight - 0.5)
    bufferCtx.lineTo(xPos + colWidth, rowHeight - 0.5)

    bufferCtx.stroke()

    // 列标题
    bufferCtx.fillStyle = '#333'
    bufferCtx.font = '14px Arial'
    bufferCtx.fillText(col.title, xPos + 8, rowHeight / 2)

    xPos += colWidth
  })
}

function renderRow (rowIndex: number, rowData: any, yPos: number, scrollLeft: number, isHovered: boolean) {
  const { bufferCtx, options } = state
  const { rowHeight } = options
  let xPos = -scrollLeft

  // 插入左侧勾选列（仅在 selectionMode 配置存在时显示）
  if (options.selectionMode) {
    // 勾选列背景
    bufferCtx.fillStyle = isHovered ? '#ededed' : rowIndex % 2 === 0 ? '#fff' : '#fafafa'
    bufferCtx.fillRect(xPos, yPos, 40, rowHeight)

    // 边框
    bufferCtx.strokeStyle = '#b1b1b1'
    bufferCtx.lineWidth = 1
    bufferCtx.beginPath()
    bufferCtx.rect(xPos + 6, yPos + 8, 14, 14)
    bufferCtx.stroke()

    // 如果是已选行，则画出对勾
    if (state.selectedRowIndices.includes(rowIndex)) {
      bufferCtx.beginPath()
      bufferCtx.moveTo(xPos + 9, yPos + 11)
      bufferCtx.lineTo(xPos + 12, yPos + 14)
      bufferCtx.lineTo(xPos + 17, yPos + 9)
      bufferCtx.lineWidth = 2
      bufferCtx.strokeStyle = '#409EFF'
      bufferCtx.stroke()
    }

    // 底部边框（与其他列保持一致）
    bufferCtx.strokeStyle = '#e0e0e0'
    bufferCtx.beginPath()
    bufferCtx.moveTo(xPos, yPos + rowHeight - 0.5)
    bufferCtx.lineTo(xPos + 40, yPos + rowHeight - 0.5)
    bufferCtx.stroke()

    xPos += 40
  }

  options.columns.forEach((col, colIndex) => {
    const colWidth = col.width || 120
    const value = rowData[col.dataIndex]

    // 行背景（斑马纹）
    bufferCtx.fillStyle = isHovered ? '#ededed' : rowIndex % 2 === 0 ? '#fff' : '#fafafa'
    bufferCtx.fillRect(xPos, yPos, colWidth, rowHeight)

    // 单元格边框（避免相邻边框合并）
    bufferCtx.strokeStyle = '#e0e0e0'
    bufferCtx.lineWidth = 1
    bufferCtx.beginPath()

    // 左侧边框（仅第一列）
    if (colIndex === 0 && !options.selectionMode) {
      bufferCtx.moveTo(xPos + 0.5, yPos)
      bufferCtx.lineTo(xPos + 0.5, yPos + rowHeight)
    }

    bufferCtx.moveTo(xPos + colWidth - 0.5, yPos)
    bufferCtx.lineTo(xPos + colWidth - 0.5, yPos + rowHeight)

    // 底部边框（所有列统一绘制）
    bufferCtx.moveTo(xPos, yPos + rowHeight - 0.5)
    bufferCtx.lineTo(xPos + colWidth, yPos + rowHeight - 0.5)

    bufferCtx.stroke() // 确保每列绘制完立即刷新

    // 单元格内容
    if (col.render) {
      const result = col.render(value, rowData)
      if (typeof result === 'string') {
        bufferCtx.fillStyle = '#333'
        bufferCtx.font = '12px Arial'
        bufferCtx.fillText(result, xPos + 8, yPos + rowHeight / 2)
      }
    } else {
      bufferCtx.fillStyle = '#333'
      bufferCtx.font = '12px Arial'
      bufferCtx.fillText(String(value || ''), xPos + 8, yPos + rowHeight / 2)
    }

    xPos += colWidth
  })
}

function swapBuffers () {
  const { bufferCtx } = state

  // 将缓冲画布内容转换为 ImageBitmap 并发送到主线程
  const imageBitmap = bufferCtx.canvas.transferToImageBitmap()
  self.postMessage({ type: 'bufferReady', buffer: imageBitmap }, [imageBitmap])
}

function resize (width: number, height: number) {
  const { mainCtx, bufferCtx, options } = state

  // 更新画布尺寸
  options.width = width
  options.height = height

  // 重置缓冲画布尺寸
  bufferCtx.canvas.width = width * options.dpr
  bufferCtx.canvas.height = height * options.dpr

  // 立即重绘
  render()
}
